package com.wanna.common.doc;

import com.wanna.common.doc.document.ApiDoc;
import com.wanna.common.doc.entity.ApiInfo;
import com.wanna.common.doc.entity.ScannerConfig;
import com.wanna.common.doc.scanner.ApiScanner;
import com.wanna.common.lang.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.List;

/**
 * 生成类
 *
 * @author wanna
 * @since 2018-12-05
 */
@SuppressWarnings("ALL")
public class Generate {

    private static final Logger logger = LoggerFactory.getLogger(Generate.class);

    private ScannerConfig scannerConfig;

    private ApiScanner scanner;

    private ApiDoc doc;

    public Generate(ApiScanner scanner, ApiDoc doc, ScannerConfig scannerConfig) {
        this.scanner = scanner;
        this.doc = doc;
        this.scannerConfig = scannerConfig;
    }

    /**
     * 生成 文档
     */
    public void generateDocument() throws Exception {
        if (scannerConfig == null || scanner == null) {
            throw new RuntimeException("请指定文档参数和扫描实现类");
        }
        // 扫描
        String[] packages = scannerConfig.getScannerPackages().toArray(new String[]{});
        List<ApiInfo> infos = scanner.scan(scannerConfig, packages);

        // 生成 文档
        doc.generateDoc(infos, scannerConfig.getLocalPath());
    }

    /**
     * commit 到本地仓库,并 push 到远程
     *
     * @param commitMessage commit 提交信息
     */
    public void commitAndPush(String commitMessage) throws Exception {
        if (scannerConfig == null || StringUtil.isEmpty(scannerConfig.getLocalPath()) || StringUtil.isEmpty(commitMessage)) {
            throw new RuntimeException("本地仓库路径: localPath 为空 或者 commitMessage 为空");
        }
        String localPath = scannerConfig.getLocalPath();
        runCommand(new File(localPath), "git", "add", "-A");
        runCommand(new File(localPath), "git", "commit", "-m", commitMessage);
        runCommand(new File(localPath), "git", "pull");
        runCommand(new File(localPath), "git", "push", "-f");
    }

    /**
     * 执行 git命令
     *
     * @param directory 仓库路径
     * @param command   命令
     * @throws Exception exception
     */
    private void runCommand(File directory, String... command) throws Exception {
        ProcessBuilder pb = new ProcessBuilder().command(command).directory(directory);
        Process process = pb.start();

        CommandInfo error = new CommandInfo(process.getErrorStream());
        CommandInfo output = new CommandInfo(process.getInputStream());
        output.start();
        error.start();

        int exit = process.waitFor();
        error.join();
        output.join();

        if (exit != 0) {
            throw new RuntimeException(String.format("runCommand returned %d", exit));
        }
    }

    /**
     * 命令行输出的信息
     */
    private class CommandInfo extends Thread {

        private InputStream is;

        private CommandInfo(InputStream is) {
            this.is = is;
        }

        @Override
        public void run() {
            try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
                String line;
                while ((line = br.readLine()) != null) {
                    logger.info(line);
                }
            } catch (IOException ioe) {
                logger.error("错误信息 {} ", ioe);
            }
        }
    }
}
